package cn.surveyking.server.core.uitls;

import lombok.SneakyThrows;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;

/**
 *
 */
@Component
public class RSAUtils {

    // 默认的公钥和私钥初始化为一个已知的值，将在应用启动时更新
    public static String DEFAULT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjWj78efU6zoma7Rmoghh\n" +
            "lJWtipCXR4KAu/eE8vicxXgYZwX6tX07z4iFxSqeMxCL+HYrjL6GZL2oNF6UrIOX\n" +
            "/GCoXmM5AD7YLwRhnsymQq+wFlGKPOqvtqIbSsleO4ApcA+EBAeXIG9kE4jDwoKD\n" +
            "e9k6Ch2JP/n2isjyAk+zI+6o22C6QvSDoV21aRFXAhX8ybW5MuVm27m3GgLO3gsA\n" +
            "l2bAC45raigf5SOWX18L9VyE5Ngrq3aRzzWsfyLmeiHKX3U3GVzxoEW1OE1zDC1W\n" +
            "UCoRpwEUDkG0jt3ULlEeRX3Ncy345tYWSV4RNBKkdHwMu3aNCCxHsGT35cUe0S5z\n" +
            "SwIDAQAB\n" +
            "-----END PUBLIC KEY-----\n";
    public static String DEFAULT_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" +
            "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCNaPvx59TrOiZr\n" +
            "tGaiCGGUla2KkJdHgoC794Ty+JzFeBhnBfq1fTvPiIXFKp4zEIv4diuMvoZkvag0\n" +
            "XpSsg5f8YKheYzkAPtgvBGGezKZCr7AWUYo86q+2ohtKyV47gClwD4QEB5cgb2QT\n" +
            "iMPCgoN72ToKHYk/+faKyPICT7Mj7qjbYLpC9IOhXbVpEVcCFfzJtbky5Wbbubca\n" +
            "As7eCwCXZsALjmtqKB/lI5ZfXwv1XITk2CurdpHPNax/IuZ6IcpfdTcZXPGgRbU4\n" +
            "TXMMLVZQKhGnARQOQbSO3dQuUR5Ffc1zLfjm1hZJXhE0EqR0fAy7do0ILEewZPfl\n" +
            "xR7RLnNLAgMBAAECggEAFIso9wbYHuhOxpzpwCZ5jq2EDbpdz+y8qRIXhXjqxaFh\n" +
            "4i2zM4SjGM5bqL49R2vi+dCpGQRg3+fRtPH8pWdkwCyGqVe+4zM+Eu6PBBP1H4EI\n" +
            "kuV7sMfjiSPZ1S6V+wzueDI42qEDqpmkL1ZSIkL1uRtg3DFYTCwTTixNRFqxyslc\n" +
            "rQts5aJvSuJw7i81LZcFUOv26Lft6hrwpJtngstFm6Yo272vkmILbB/CWD9Zq6H2\n" +
            "O9HvRaCR/ARKWbY9arKgkgaHaaD4sNl65x/o2KvU3+SCo7PlBU1bExgLpBnwDCz+\n" +
            "ClfjGJENTe9L9KIqg8ZUFJoloz2B/5iWcenO2zJKOQKBgQDUlRtUe1Ax9Xxr8r99\n" +
            "Hho1MsgPeUfSUDwmspOdzWM1GcpHDppTBIcZemPQu4whW8c8jesvRi8KrxatG6l5\n" +
            "FrrQTEFfpj7r1fOvg+QfM4DrfU7eyiQrCGVZW+aGJ4Tv62+VWUb4Tla1OD1hPLs1\n" +
            "X0yFz5vOR2uDNdiC65nnNNPpzwKBgQCqSp/L3yjuqVU0sBkiflCdFM9kSDTjdcTZ\n" +
            "yxtMUveIn1yghBrAcdiwNbHANVl+Imz7LVNYhoRiuvYXWHz5GYNWHyo7F5SW/W4E\n" +
            "74QitN4QipkYBdpIXLm9yPh31VXKHEr65S1UUAD0oNPYOCNf+SwyYzQx4GxOW3NQ\n" +
            "zKrqCfjJxQKBgDEyfMu1ah7VwEC/Qh+zmr8bDH/AQqXimbke9Ni9UqtUV6LQN1jl\n" +
            "IFr+HyGMdea2dcqG0Zn0NSjU0nunfjYe04cnTq3TLJapwiapcF7kLX7SVjFrOKmY\n" +
            "3NOsWBJODQ71PrKiobEPeDOiW1ooku7MKkqBfH5luvT3vi62VbzTVgOzAoGBAIHh\n" +
            "kslK9ow5CKy71x/Q2alFEvz4eaY2z6IRYEuxR+yjJ2GiAElhS5TyDxV7WztyBE76\n" +
            "/gOZ7WTkFgguTHstM1e/Q1V4obMbrgsDp3NVIb3aB/Qjmp3wYxZWLvQu+VTCiYmc\n" +
            "vBr/PgtWktzpzElJ4aS4tzmHYvPMmkI5J+6DFobFAoGBAMu7lz9HAAJSC2pYGO29\n" +
            "VB/T/2rdvvC2yBp3InfsK3CLmBg/zcr5AD2dYtj34waU+aQajlbvZaM1WKSJ9CyE\n" +
            "JR7kOGMDHXaGEyKZSdQGkqVIuMGxUi6pw2kExKnHHBv6WZaeWVRXacmALjM6MTjI\n" +
            "25zW6+To5vlBRUh2zBVbI8ax\n" +
            "-----END RSA PRIVATE KEY-----\n";

    @PostConstruct
    @SneakyThrows
    public void init() {
        // 在 Spring 容器初始化后生成新的密钥对
        HashMap<String, String> keyPair = genKeyPair();
        DEFAULT_PUBLIC_KEY = keyPair.get("publicKey");
        DEFAULT_PRIVATE_KEY = keyPair.get("privateKey");
    }

    /**
     * 生成随机 RSA 密钥对
     *
     * @return 包含公钥和私钥的 HashMap
     * @throws NoSuchAlgorithmException 如果没有 RSA 算法则抛出异常
     */
    public static HashMap<String, String> genKeyPair() throws NoSuchAlgorithmException {
        HashMap<String, String> keyMap = new HashMap<>();
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024, new SecureRandom());  // 建议将密钥长度改为 2048
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyStr = Base64Utils.encodeToString(publicKey.getEncoded());
        String privateKeyStr = Base64Utils.encodeToString(privateKey.getEncoded());
        keyMap.put("publicKey", publicKeyStr);
        keyMap.put("privateKey", privateKeyStr);
        return keyMap;
    }

    /**
     * 使用 RSA 公钥加密字符串
     *
     * @param str       待加密的字符串
     * @param publicKey 公钥
     * @return 加密后的字符串，以 Base64 编码
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        byte[] decoded = Base64Utils.decodeFromString(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPublicKey RSAKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, RSAKey);
        return Base64Utils.encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
    }

    /**
     * 使用 RSA 私钥解密字符串
     *
     * @param str        加密后的字符串
     * @param privateKey 私钥
     * @return 解密后的明文字符串
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception {
        byte[] inputByte = Base64Utils.decodeFromString(str);
        byte[] decoded = Base64Utils.decodeFromString(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(decoded);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey RSAKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, RSAKey);
        byte[] bytes = cipher.doFinal(inputByte);
        return new String(bytes);
    }

    /**
     * 使用 RSA 私钥解密字符串
     *
     * @param str        加密后的字符串
     * @return 解密后的明文字符串
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str) throws Exception {
       return decrypt(str, DEFAULT_PRIVATE_KEY);
    }
}
